
public class HashingList extends Hashing
{
    
    private float loadFactor; // factor de carga, al inicio es 0 (n/M)
    private int M;            // cantidad de celdas, al inicio es 7
    private int N;            // cantidad de elementos que han sido insertados

    public HashingList(int M,boolean verbosa)
    {
        super(M,verbosa);
        this.M = M;
        this.N = 0;
        this.loadFactor = 0;
        
        //System.out.println("CREANDO NUEVO HASH CON TAMANIO " + M);
    }
    
    @Override
    public void insert(int x)
    {
        int pos = funcionHash(x);
        if(hashes[pos] == null) {
            hashes[pos] = new NodoHashLista(x, null);
        }
        else {
            if(verbosa)
                System.out.println("Se ha detectado una colision al insertar el " + x);
            hashes[pos].insert(x);
        }
        
        N++;
        reloadFactor();
        if(loadFactor > log2(M))
        {   
            this.N = 0;
            this.M = this.M * 2;
            
            rehash(this.hashes);
        }
    }
    
    @Override
    public boolean search(int x){
        int pos = super.funcionHash(x);
        if(this.hashes[pos] != null)
        {
            return hashes[pos].search(x);
        }
        return false;  
    }

    private void reloadFactor()
    {
        this.loadFactor = (float)N / M;
    }

    private void rehash( Nodo[] hashes )
    { 
        HashingList hash = new HashingList(hashes.length * 2 + 1, this.verbosa);
        for(int i=0; i<hashes.length; i++)
        {
            if(hashes[i] !=null)
            {
                NodoHashLista list = (NodoHashLista) hashes[i];
                while(list != null){
                    hash.insert(list.value);
                    list = list.sgteNodo; 
                }
            }
        }
        this.hashes = hash.hashes;
        this.M = hash.M;
    }
    
    private int log2(int x)
    {
        return (int)(Math.log(x)/Math.log(2));
    }

  

    @Override
    public void imprimir()
    {
        System.out.println("imprimiendo los numeros de la tabla de hash");
        for(int i = 0; i<M; i++)
        {
            if(this.hashes[i] !=null)
            {
                System.out.print("\n |"+i+((i<10)?" ":"")+"|");
                this.hashes[i].imprimir();
            }
        }
        System.out.println("\n");
    }
}
